#include <format>
#include <iostream>
#include <memory>
#include <vector>

#include "proxy/proxy.h"

// 1. 复合 Facade
PRO_DEF_MEM_DISPATCH(AreaDispatch, area);
PRO_DEF_MEM_DISPATCH(PerimeterDispatch, perimeter);

void advanced_features_example()
{
    struct Shape : pro::facade_builder ::add_convention<AreaDispatch, double() const>::add_convention<
                       PerimeterDispatch, double() const>::support_copy<pro::constraint_level::nontrivial>::build
    {
    };

    class Square
    {
    public:
        Square(double side) : side_(side) {}
        double area() const { return side_ * side_; }
        double perimeter() const { return 4 * side_; }

    private:
        double side_;
    };

    // 2. 创建代理
    pro::proxy<Shape> square = pro::make_proxy<Shape, Square>(5.0);
    std::cout << std::format("Square: area={}, perimeter={}\n", square->area(), square->perimeter());

    // 3. 类型检查
    std::cout << std::format("Square has value: {}\n", square.has_value());

    // 4. 复制和移动
    auto square_copy = square;  // 复制
    std::cout << std::format("Copy area: {}\n", square_copy->area());

    // 5. 重置和重新赋值
    square.reset();
    std::cout << std::format("After reset: {}\n", square.has_value());

    square = pro::make_proxy<Shape, Square>(3.0);
    std::cout << std::format("After reassign: area={}\n", square->area());

    // 6. 容器中的代理
    std::vector<pro::proxy<Shape>> shapes;
    shapes.reserve(3);
    shapes.push_back(pro::make_proxy<Shape, Square>(2.0));
    shapes.push_back(pro::make_proxy<Shape, Square>(4.0));
    shapes.push_back(pro::make_proxy<Shape, Square>(6.0));

    double total_area = 0.0;
    for (const auto& shape : shapes)
    {
        total_area += shape->area();
    }
    std::cout << std::format("Total area of {} shapes: {}\n", shapes.size(), total_area);
}